package org.leumasjaffe.initiativeTracker.operator;


import java.util.Hashtable;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.leumasjaffe.initiativeTracker.Constants;
import org.leumasjaffe.initiativeTracker.entity.Character;
import org.leumasjaffe.initiativeTracker.entity.CharacterList;
import org.leumasjaffe.initiativeTracker.entity.NPC;
import org.leumasjaffe.initiativeTracker.entity.PC;
import org.leumasjaffe.initiativeTracker.view.InitiativeFrame;

import org.leumasjaffe.util.array.Sort;
import org.leumasjaffe.util.io.PortableScanner;

@NonNullByDefault
public class InitiativeController{
	
	public static Hashtable<String, InitiativeController> instances = 
			new Hashtable<String, InitiativeController>();
	
	public final String id;
	public final UnitManager root;
	public final CharacterList list;
	
	@SuppressWarnings("null")
	public static synchronized InitiativeController tracker(String id) {
		if (instances.containsKey(id))
			return instances.get(id);
		instances.put(id, new InitiativeController(id));
		if (!Constants.client)
			CharacterImporter.importTracker(id);
		return instances.get(id);
	}
	
	private InitiativeController(String id) {
		this.id = id;
		this.list = new CharacterList();
		this.root = new UnitManager(this);			
	}

	/**
	 * A method to re-roll initiative for all actors, and possibly reset the turn numbers
	 */
	public void reroll() {
		if (this.root.getSubTurn() > 0 || this.root.getTurnNum() > 1) {
			System.out.print("Reset Turns: ");
			String t = PortableScanner.nextLine();
			if (t.equalsIgnoreCase("Y") || t.equalsIgnoreCase("YES") 
					|| t.equalsIgnoreCase("TRUE")) {
				InitiativeFrame.getInstance().reset();
			}
		}
		int x = 0;
		boolean exception = false;
		for (int n = 0; n < this.list.size(); n++) {
			if (x!=n)
				break;
			else {
				Character c = this.list.get(n).getCharacter();
				if (c instanceof PC)
					x++;
				else {
					System.out.print("Is " + c.getName() + " continuing: ");
					String s = PortableScanner.nextLine();
					if (s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("YES") 
							|| s.equalsIgnoreCase("TRUE"))
						x++;
					else if (s.equalsIgnoreCase("New"))
						exception = true;
				}
			}
		}
		if (exception || x == this.list.size()){
			newRoll(exception);
			PortableScanner.nextLine();
			this.root.changeTurn();
		}
	}
	
	/**
	 * Roll initiative for a given Character
	 * @param c The character to roll initiative for
	 * @return Returns the integer representing the initiative roll
	 */
	public int rollInit(Character c) {
		String s;
		if (c instanceof NPC)
			s = ((NPC) c).getName();
		else
			s = c.getName();
		System.out.print("Initiative Roll for " + s + ": ");
		int inputNum = PortableScanner.nextInt("Initiative Roll for " + s);
		c.setInit(inputNum);
		return inputNum;
	}
	
	/**
	 * A helper method for use with reroll(). Rolls all
	 * initiatives and then sorts the allPieces list. 
	 * @param exception Is this a new encounter?
	 */
	@SuppressWarnings("all")
	private void newRoll(boolean exception) {
		Constants.pageNum = 0;
		
		System.out.println("Please reroll the Initiative for all characters...");
		
		System.out.print("Is this an extended rest: ");
		String s = PortableScanner.nextLine();
		boolean extrest = false;
		if (s.equalsIgnoreCase("Y") || s.equalsIgnoreCase("YES") ||
				s.equalsIgnoreCase("TRUE"))
			extrest = true;
				
		for (int i = 0; i < this.list.size(); i++) {
			Character c = this.list.get(i).getCharacter();
			checkRoll(c, extrest, exception);
		}
		
		this.list.setList(Sort.insertionSort(this.list.getList()));
	}
	
	/**
	 * Method to call the rollInit() method and fix player character health
	 * @param c The Character that we are rolling initiative for
	 * @param extrest Is this an extended rest? Only meaningful for PlayerCharacters (PC)
	 * @param exception Is this a new encounter? Only meaningful for (PC)
	 */
	private void checkRoll(Character c, boolean extrest, boolean exception) {
		rollInit(c);
		if (c instanceof PC) {
			((PC) c).nullTemp();
			if (extrest) {
				((PC) c).setSurgeLeft(((PC) c).getSurgeMax());
				((PC) c).setHp(((PC) c).getMaxHP());
			}
			else if (exception) {
				System.out.println("How many healing surges woulg you like to use?");
				System.out.println("HP = " + c.getHp() + "/" + c.getMaxHP());
				System.out.println("You have " + ((PC) c).getSurgeLeft() +
						" Surges left at " +
						((PC) c).getSurgevalue() + " HP per surge.");
				int needed = (c.getMaxHP()-c.getHp())/((PC) c).getSurgevalue();
				if (needed > ((PC) c).getSurgeLeft()) {
					needed = ((PC) c).getSurgeLeft();
					System.out.println("The maximum number of surges you can use is "
							+ needed);
				}
				else
					System.out.println("The maximum number of surges needed is " + needed);
				System.out.print("Please enter the number of surges to use: ");
				int i = PortableScanner.nextInt("Please enter the number" +
				" of surges to use");
				if (i > needed)
					i = needed;
				for (int ii = i; ii>=1; ii--) {
					((PC) c).surge(0);
				}
			}
		}
	}

}
